package com.luban.controller;


import com.alibaba.fastjson.JSONObject;
import com.luban.util.SensitiveFilter;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

@Component
@WebFilter(urlPatterns = "/*", filterName = "testFilter")
public class CharacterFilter implements Filter {
    static StringBuilder sb = new StringBuilder();
    static String[] words = {"傻", "禽", "畜"};
    SensitiveFilter filter=null;
   //static SensitiveFilter filter = SensitiveFilter.DEFAULT;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 使用默认单例（加载默认词典）
         filter = SensitiveFilter.DEFAULT;
    }


    @Override
    public void destroy() {

    }


    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;

        HttpServletResponse resp = (HttpServletResponse) response;
//        String requestPath = req.getRequestURI();
//        requestPath = requestPath.substring(req.getContextPath().length() + 1);
//        while (requestPath.endsWith("/")) { //预防uri末尾有 ‘/’
//            requestPath = requestPath.substring(0, requestPath.length() - 1);
//        }

        Map<String, Object> paramMap = new HashMap<>();
        String type = req.getContentType();
        ServletRequest requestWrapper = null;
        if (req instanceof HttpServletRequest) {
            requestWrapper = new ReaderReuseHttpServletRequestWrapper(req);
        }
        BufferedReader reader = requestWrapper.getReader();

        // 读取Request Payload数据
        String Payload = IOUtils.toString(reader);
        if (type != null && type.startsWith("application/json")) {
            JSONObject jsonObject = JSONObject.parseObject(Payload);
            if (jsonObject != null) {
                for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {

                    String alreadyFilter = filter.filter(entry.getValue().toString(), '*');
                    if(!(alreadyFilter.equals(entry.getValue().toString()))){
                        response.getWriter().write(alreadyFilter);
                        return;//如果有敏感词汇，就不会请求到后台
                    }
                    paramMap.put(entry.getKey(), entry.getValue());

                }
            }
        } else if (type != null && type.startsWith("text/plain")) {
            String[] kvs = Payload.split("&");
            for (String kv : kvs) {
                String[] lf = kv.split("=");
                paramMap.put(lf[0], lf[1]);
            }

        }
        // 获取请求参数
        Enumeration en = req.getParameterNames();
        while (en.hasMoreElements()) {
            String name = (String) en.nextElement();
            String value = req.getParameter(name);
            String alreadyFilter = filter.filter(value, '*');
            if(!(alreadyFilter.equals(value))){
                response.getWriter().write(alreadyFilter);
                return;//如果有敏感词汇，就不会请求到后台
            }

            paramMap.put(name, value);
        }


        requestWrapper.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        filterChain.doFilter(requestWrapper, resp);

    }

    /**
     * 两个方法都注明方法只能被调用一次，由于RequestBody是流的形式读取，
     * 那么流读了一次就没有了，所以只能被调用一次。
     * 既然是因为流只能读一次的原因，那么只要将流的内容保存下来，就可以实现反复读取了
     *
     * @author LIU
     */
    static class ReaderReuseHttpServletRequestWrapper extends HttpServletRequestWrapper {


        private final byte[] body;

        public ReaderReuseHttpServletRequestWrapper(HttpServletRequest request)
                throws IOException {
            super(request);
            body = IOUtils.toString(request.getReader()).getBytes(Charset.forName("UTF-8"));
        }

        @Override
        public BufferedReader getReader() throws IOException {
            return new BufferedReader(new InputStreamReader(getInputStream()));
        }

        @Override
        public ServletInputStream getInputStream() throws IOException {
            final ByteArrayInputStream bais = new ByteArrayInputStream(body);
            return new ServletInputStream() {
                @Override
                public boolean isFinished() {
                    return false;
                }

                @Override
                public boolean isReady() {
                    return false;
                }

                @Override
                public void setReadListener(ReadListener listener) {

                }

                @Override
                public int read() throws IOException {
                    return bais.read();

                }
            };
        }
    }


}
